#!/usr/bin/env python
# -*- coding: utf-8 -*-

from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QTreeWidget, QTreeWidgetItem,
                           QSplitter, QTextEdit, QLabel, QHBoxLayout)
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QFont, QColor

class PacketDetailWidget(QWidget):
    """
    数据包详细信息窗口组件，显示选中数据包的详细协议信息
    """
    
    def __init__(self, parent=None):
        """
        初始化数据包详细信息窗口组件
        """
        super().__init__(parent)
        self.current_packet = None
        self._setup_ui()
        
    def _setup_ui(self):
        """
        设置UI组件
        """
        # 创建主布局
        layout = QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        
        # 创建分割器
        self.splitter = QSplitter(Qt.Vertical)
        
        # 创建协议树
        self.tree = QTreeWidget()
        self.tree.setHeaderLabels(["协议字段", "值"])
        self.tree.setColumnWidth(0, 250)
        
        # 创建原始数据区域
        self.raw_data_container = QWidget()
        raw_data_layout = QVBoxLayout(self.raw_data_container)
        raw_data_layout.setContentsMargins(0, 0, 0, 0)
        
        # 添加标题
        raw_data_header = QHBoxLayout()
        raw_data_header.addWidget(QLabel("原始数据"))
        raw_data_header.addStretch()
        raw_data_layout.addLayout(raw_data_header)
        
        # 添加文本编辑器
        self.raw_data_text = QTextEdit()
        self.raw_data_text.setReadOnly(True)
        self.raw_data_text.setFont(QFont("Courier New", 10))
        raw_data_layout.addWidget(self.raw_data_text)
        
        # 将组件添加到分割器
        self.splitter.addWidget(self.tree)
        self.splitter.addWidget(self.raw_data_container)
        self.splitter.setStretchFactor(0, 3)  # 协议树占比较大
        self.splitter.setStretchFactor(1, 1)  # 原始数据占比较小
        
        # 添加分割器到主布局
        layout.addWidget(self.splitter)
        self.setLayout(layout)
        
    def display_packet(self, packet):
        """
        显示数据包详细信息
        
        Args:
            packet: 解析后的数据包
        """
        self.current_packet = packet
        
        # 清空树
        self.tree.clear()
        
        if not packet:
            return
            
        # 添加基本信息
        frame_item = QTreeWidgetItem(self.tree, ["数据帧信息"])
        frame_item.setExpanded(True)
        
        # 添加帧基本信息
        self._add_tree_item(frame_item, "编号", str(packet.get("number", "")))
        self._add_tree_item(frame_item, "时间", packet.get("time", ""))
        self._add_tree_item(frame_item, "长度", str(packet.get("length", "")))
        
        # 添加各层协议信息
        if "layers" in packet:
            for layer in packet.get("layers", []):
                layer_name = layer.get("name", "未知协议")
                layer_item = QTreeWidgetItem(self.tree, [layer_name])
                layer_item.setExpanded(True)
                
                # 添加特殊字段
                self._add_special_fields(layer, layer_item)
                
                # 添加一般字段
                for field_name, field_value in layer.get("fields", {}).items():
                    self._add_tree_item(layer_item, field_name, field_value)
        
        # 生成并显示原始数据
        self._display_raw_data(packet)
        
    def _add_tree_item(self, parent, name, value):
        """
        添加树节点
        
        Args:
            parent: 父节点
            name: 字段名
            value: 字段值
        """
        return QTreeWidgetItem(parent, [name, str(value)])
    
    def _add_special_fields(self, layer, layer_item):
        """
        添加特殊协议字段
        
        Args:
            layer: 协议层数据
            layer_item: 协议层树节点
        """
        # 根据协议类型添加特殊字段
        layer_name = layer.get("name", "").lower()
        
        if "ipv4" in layer_name:
            # 添加IP地址信息
            if "source_ip" in layer:
                self._add_tree_item(layer_item, "源IP地址", layer["source_ip"])
            if "dest_ip" in layer:
                self._add_tree_item(layer_item, "目标IP地址", layer["dest_ip"])
            if "ttl" in layer:
                self._add_tree_item(layer_item, "存活时间(TTL)", layer["ttl"])
                
        elif "tcp" in layer_name:
            # 添加TCP特有信息
            if "source_port" in layer:
                port_info = f"{layer['source_port']}"
                if "source_service" in layer:
                    port_info += f" ({layer['source_service']})"
                self._add_tree_item(layer_item, "源端口", port_info)
                
            if "dest_port" in layer:
                port_info = f"{layer['dest_port']}"
                if "dest_service" in layer:
                    port_info += f" ({layer['dest_service']})"
                self._add_tree_item(layer_item, "目标端口", port_info)
                
            if "sequence" in layer:
                self._add_tree_item(layer_item, "序列号", layer["sequence"])
                
            if "acknowledgment" in layer:
                self._add_tree_item(layer_item, "确认号", layer["acknowledgment"])
                
            if "flags" in layer:
                self._add_tree_item(layer_item, "标志", layer["flags"])
                
        elif "udp" in layer_name:
            # 添加UDP特有信息
            if "source_port" in layer:
                port_info = f"{layer['source_port']}"
                if "source_service" in layer:
                    port_info += f" ({layer['source_service']})"
                self._add_tree_item(layer_item, "源端口", port_info)
                
            if "dest_port" in layer:
                port_info = f"{layer['dest_port']}"
                if "dest_service" in layer:
                    port_info += f" ({layer['dest_service']})"
                self._add_tree_item(layer_item, "目标端口", port_info)
                
            if "udp_length" in layer:
                self._add_tree_item(layer_item, "UDP长度", layer["udp_length"])
                
        elif "http" in layer_name:
            # 添加HTTP特有信息
            if "method" in layer:
                self._add_tree_item(layer_item, "请求方法", layer["method"])
                
            if "uri" in layer:
                self._add_tree_item(layer_item, "请求URI", layer["uri"])
                
            if "version" in layer:
                self._add_tree_item(layer_item, "HTTP版本", layer["version"])
                
            if "status_code" in layer:
                status_info = f"{layer['status_code']}"
                if "status_message" in layer:
                    status_info += f" ({layer['status_message']})"
                self._add_tree_item(layer_item, "状态码", status_info)
                
            # 添加HTTP头部信息
            if "headers" in layer:
                headers_item = QTreeWidgetItem(layer_item, ["HTTP头部"])
                for header_name, header_value in layer["headers"].items():
                    self._add_tree_item(headers_item, header_name, header_value)
                    
        elif "dns" in layer_name:
            # 添加DNS特有信息
            if "query_name" in layer:
                self._add_tree_item(layer_item, "查询名称", layer["query_name"])
                
            if "query_type" in layer:
                self._add_tree_item(layer_item, "查询类型", layer["query_type"])
                
            # 添加DNS响应记录
            if "responses" in layer:
                responses_item = QTreeWidgetItem(layer_item, ["DNS响应"])
                for resp in layer["responses"]:
                    resp_item = self._add_tree_item(responses_item, resp.get("name", "未知"), "")
                    self._add_tree_item(resp_item, "类型", resp.get("type", ""))
                    self._add_tree_item(resp_item, "数据", resp.get("data", ""))
        
    def _display_raw_data(self, packet):
        """
        显示原始数据
        
        Args:
            packet: 解析后的数据包
        """
        if not packet:
            self.raw_data_text.clear()
            return
            
        # 生成十六进制和ASCII展示
        html = "<pre>"
        
        # 尝试获取原始数据
        raw_data = None
        for layer in packet.get("layers", []):
            if "raw_data" in layer:
                raw_data = layer["raw_data"]
                break
                
        if raw_data:
            # 将原始数据转换为可读形式
            offset = 0
            while offset < len(raw_data):
                # 添加偏移量
                html += f"<span style='color:#808080;'>{offset:04x}</span>  "
                
                # 处理16字节
                hex_part = ""
                ascii_part = ""
                
                for i in range(16):
                    if offset + i < len(raw_data):
                        byte = raw_data[offset + i]
                        hex_part += f"{byte:02x} "
                        
                        # ASCII部分
                        if 32 <= byte <= 126:  # 可打印字符
                            ascii_part += chr(byte)
                        else:
                            ascii_part += "."
                    else:
                        hex_part += "   "
                        ascii_part += " "
                        
                    # 在中间位置添加额外空格
                    if i == 7:
                        hex_part += " "
                        
                # 添加行
                html += f"{hex_part}  <span style='color:#0000FF;'>{ascii_part}</span><br>"
                offset += 16
        else:
            # 如果没有原始数据，显示默认信息
            html += "原始数据不可用"
            
        html += "</pre>"
        self.raw_data_text.setHtml(html)
        
    def clear(self):
        """
        清空显示
        """
        self.tree.clear()
        self.raw_data_text.clear()
        self.current_packet = None 